from PySide6 import QtCore, QtWidgets
import paramiko
import os
from enum import Enum

class FileType(Enum):
    FILE = 0
    DIRECTORY = 1

class RemoteDialog(QtWidgets.QDialog):
    def __init__(self, ssh_configure, file_type, extensions, window_name='Remote Dialog', parent=None):
        QtWidgets.QDialog.__init__(self, parent=parent)
        trans = paramiko.Transport((ssh_configure["ip"], ssh_configure["port"]))
        trans.connect(username=ssh_configure['username'], password=ssh_configure['password'])
        self.sftp = paramiko.SFTPClient.from_transport(trans)
        window_name += '({}@{}:{})'.format(ssh_configure['username'], ssh_configure["ip"], ssh_configure["port"])
        self.file_type = file_type
        self.extensions = extensions
        self.setWindowTitle(window_name)
        self.current_view = QtWidgets.QListWidget()
        self.jump_to_button = QtWidgets.QPushButton("前往")
        self.current_path = ssh_configure['work_directory']
        self.current_path_label = QtWidgets.QLineEdit(self.current_path)
        self.select_ok = QtWidgets.QPushButton("ok")
        self.select_cancel = QtWidgets.QPushButton("cancel")
        self.current_children = []

        lineLayout = QtWidgets.QHBoxLayout()
        lineLayout.addWidget(self.current_path_label)
        lineLayout.addWidget(self.jump_to_button)

        subLayout = QtWidgets.QHBoxLayout()
        subLayout.addWidget(self.select_ok)
        subLayout.addWidget(self.select_cancel)

        mainLayout = QtWidgets.QVBoxLayout()
        mainLayout.addLayout(lineLayout)
        mainLayout.addWidget(self.current_view)
        mainLayout.addLayout(subLayout)

        self.setLayout(mainLayout)
        self.current_view.itemDoubleClicked.connect(self.itemDoubleClickSlot)
        self.viewCurrentDirectory()
        self.select_ok.clicked.connect(self.pushOk)
        self.select_cancel.clicked.connect(self.pushCancel)
        self.jump_to_button.clicked.connect(self.pushJump)

        self.exec_()

    def is_dir_stmode(self, st_mode):
        if oct(st_mode)[2] == '4':
            return True
        else:
            return False

    def is_file(self, filename):
        ziped = list(zip(*self.current_children))
        idx = ziped[0].index(filename)
        return not ziped[1][idx]

    def viewCurrentDirectory(self):
        dir_list = []
        if self.file_type == FileType.FILE:
            dir_list = [(file.filename, self.is_dir_stmode(file.st_mode)) for file in self.sftp.listdir_attr(self.current_path) if self.checkExt(file.filename) or self.is_dir_stmode(file.st_mode)]
            dir_list.sort(key=lambda x: x[1], reverse=True)
        elif self.file_type == FileType.DIRECTORY:
            dir_list = [(file.filename, True) for file in self.sftp.listdir_attr(self.current_path) if self.is_dir_stmode(file.st_mode)]
        self.current_children = []
        self.current_view.clear()
        if self.current_path != '/':
            self.current_children.append(("..", True))
        self.current_children += dir_list
        folder_icon = QtWidgets.QFileIconProvider().icon(QtWidgets.QFileIconProvider().Folder)
        file_icon = QtWidgets.QFileIconProvider().icon(QtWidgets.QFileIconProvider.File)
        for file in self.current_children:
            if file[1]:
                item = QtWidgets.QListWidgetItem(file[0])
                item.setIcon(folder_icon)
                self.current_view.addItem(item)
            else:
                item = QtWidgets.QListWidgetItem(file[0])
                item.setIcon(file_icon)
                self.current_view.addItem(item)

    def checkExt(self, filename):
        if self.extensions == None:
            return True
        else:
            file_ext = os.path.splitext(filename)[1]
            if file_ext in self.extensions:
                return True
            else:
                return False

    def itemDoubleClickSlot(self, item):
        if item.text() == "..":
            self.current_path = os.path.dirname(self.current_path)
        else:
            self.current_path = os.path.join(self.current_path, item.text()).replace('\\', '/')
        self.current_path_label.setText(self.current_path)
        if not self.is_file(item.text()):
            self.viewCurrentDirectory()
        else:
            self.sftp.close()
            self.accept()

    def pushOk(self):
        selected_list = self.current_view.selectedItems()
        if len(selected_list) > 0:
            self.current_path = os.path.join(self.current_path, selected_list[0].text()).replace('\\', '/')
        self.sftp.close()
        self.accept()

    def pushCancel(self):
        self.current_path = ""
        self.accept()

    def closeEvent(self, event):
        self.pushCancel()

    def pushJump(self):
        try:
            PATH = self.current_path_label.text().replace('\\', '/')
            _ = self.sftp.listdir(PATH)
            self.current_path = PATH
            self.viewCurrentDirectory()
        except:
            self.current_path_label.setText(self.current_path)
            QtWidgets.QMessageBox.information(self, "提示", "该文件夹不存在！")

    def sizeHint(self):
        return QtCore.QSize(400, 500)

    @staticmethod
    def getRemotePath(ssh_configure, file_type=FileType.FILE, extensions=None):
        return RemoteDialog(ssh_configure, file_type, extensions).current_path

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ftp_host = "ae-git.hsxp-cd.com"  # FTP连接信息
    # ftp_host = "127.0.0.1"
    ftp_port = 22  # FTP默认端口21,SFTP默认端口22
    ftp_user = "upload"  # 如果未指定，使用默认用户名为Anonymous，密码为空
    ftp_password = "1qazCFT^"
    sftp_configure = {"ip": "ae-git.hsxp-cd.com", "port": 22, "username": 'upload', "password": '1qazCFT^', 'work_directory': "D:\\pyside2_Test"}
    path = RemoteDialog.getRemotePath(sftp_configure, FileType.FILE, ['.tif', '.tiff'])
    print(path)
    sys.exit(app.exec_())